/*
 * SensorDefects.cpp
 *
 *  Created on: 10 Nov 2013
 *      Author: thomas
 */

#include "SensorDefects.h"
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <random>
#include <unistd.h>

using namespace std;
using namespace cv;

#include <boost/random.hpp>

SensorDefectSet::SensorDefectSet(int width, int height, double lamdaC)
{
	_c = Mat::zeros(height,width,CV_8UC1);
	_nrOfPixels = width*height;
	_nrOfdefects_c = 0;
	_lamdaC = lamdaC*_nrOfPixels / 1000 / 365;		// to calc it per day
	_ageInDays = 0;

}



int myRand()
{
	int upperBorder = rand() % 10;
	for(int i=0; i<upperBorder; i++)
		rand();
	return rand();

}


SensorDefectSet::SensorDefectSet()
{

}

int SensorDefectSet::getAge()
{
	return _ageInDays;
}

int SensorDefectSet::getExpectedDefectsC(int ageInDays)
{
	return (int)(_lamdaC * (double)ageInDays);
}


void SensorDefectSet::ageBy(int nrOfDays, SensorDefectSet& newSet)
{
	int nrOfCToAdd = getExpectedDefectsC(nrOfDays+this->_ageInDays) - this->_nrOfdefects_c;


	cout << this << " adding " << nrOfCToAdd << " defects..." << endl;

	newSet._c = this->_c.clone();
	newSet._nrOfdefects_c = 0;
	newSet._ageInDays = nrOfDays + this->_ageInDays;
	newSet._lamdaC = _lamdaC;

	for(int i=0; i<nrOfCToAdd; i++)
	{

		int x = myRand() % _c.cols;
		int y = myRand() % _c.rows;


		int amount = (rand() % 2) + 1;		// some value
		//amount = 0;
		newSet._c.at<uchar>(y,x) = amount;	// minimum offset is 128
		newSet._nrOfdefects_c++;
	}

	usleep(rand()%1535);

	return;
}

void SensorDefectSet::apply(cv::Mat& on)
{
	add(on,_c,on);
}

SensorDefects::SensorDefects(const cv::Size& imgSize)
{
	_width = imgSize.width;
	_height = imgSize.height;
}

SensorDefects::~SensorDefects() {
}



void SensorDefects::calcDefects(int timespan, int stepwidth)
{

	SensorDefectSet s(_width,_height); // zero day

	_defectsOverTime.push_back(s);

	for(int i = stepwidth; i<timespan; i+=stepwidth)
	{
		SensorDefectSet nextOlder;

		_defectsOverTime.back().ageBy(stepwidth, nextOlder);
		_defectsOverTime.push_back(nextOlder);

	}
}

void SensorDefects::applyDefects(cv::Mat& applyOn, int age)
{
	vector<SensorDefectSet>::iterator it = lower_bound(_defectsOverTime.begin(), _defectsOverTime.end(), age, SensorDefectSet::cmp);

	if(it == _defectsOverTime.end())
	{
		cerr << "No aging matrix found" << endl;
	}
	else
	{
		it->apply(applyOn);
	}


}

